#include <iostream>
using namespace std;
#include <vector>

//
//template<class T>
//class SmartPtr
//{
//public:
//	SmartPtr(T* ptr)
//		:_ptr(ptr)
//	{}
//
//	~SmartPtr()
//	{
//		if (_ptr)
//			delete _ptr;
//	}
//
//	
//private:
//	T* _ptr;
//};
//
//int main()
//{
//	return 0;
//}


//template<class T>
//class Copy_Ban
//{
//
//public:
//	Copy_Ban(Copy_Ban<T>& cb) = delete;
//	Copy_Ban<T>& operator=(Copy_Ban<T>& cb) = delete;
////private:
////	Copy_Ban(Copy_Ban<T>& cb);
////	Copy_Ban<T>& operator=(Copy_Ban<T>& cb);
//};
//
//int main()
//{
//	Copy_Ban<int> cb1;
//	Copy_Ban<int> cb2(cb1);
//
//	return 0;
//}


//class HeapOnly
//{
//public:
//	template<class... Args>
//	static HeapOnly* GetInstance(Args... args)
//	{
//		return new HeapOnly(args...);
//	}
//
//	HeapOnly(const HeapOnly&) = delete;
//	HeapOnly& operator=(const HeapOnly&) = delete;
//private:
//	HeapOnly(int x)
//		:_data(x)
//	{}
//
//	HeapOnly()
//	{}
//
//	int _data;
//	vector<int> _v;
//};

//int main()
//{
//	HeapOnly* ho1 = HeapOnly::GetInstance();
//
//	return 0;
//}


class StackOnly
{
public:
	template<class... Args>
	static StackOnly GetInstance(Args... args)
	{
		return  StackOnly(args...);
	}

	void* operator new(size_t) = delete;
	void operator delete(void*) = delete;
private:
	StackOnly(int x)
		:_data(x)
	{}

	StackOnly()
	{}

	int _data;
	vector<int> _v;
};

//struct A
//{
//private:
//	A() {}
//};
//
//struct B : public A
//{
//public:
//	B() {}
//};

//struct A final
//{
//public:
//	A() {}
//};
//
//struct B : public A
//{
//public:
//	B() {}
//};

namespace hunger
{
	class Singleton
	{
	public:
		static Singleton* GetInstance()
		{
			return &_sint;
		}

		Singleton(const Singleton&) = delete;
		Singleton& operator=(const Singleton&) = delete;

	private:
		Singleton() {}

		Singleton(int x, const vector<string>& vstr = {"string", "iterator"})
			:_a(x)
			,_vstr(vstr)
		{}

		int _a;
		vector<string> _vstr;

		static Singleton _sint;
	};

	Singleton Singleton::_sint;
}

namespace lazy
{
	class Singleton
	{
	public:
		static Singleton* GetInstance()
		{
			if (_sint == nullptr)
			{
				_sint = new Singleton;
			}
			return _sint;
		}

		static void DestroyInstance()
		{
			if (_sint)
			{
				delete _sint;
				_sint = nullptr;
			}
		}

		Singleton(const Singleton&) = delete;
		Singleton& operator=(const Singleton&) = delete;

	private:
		~Singleton()
		{
			cout << "~Singleton()" << endl;
		}

		Singleton() {}

		Singleton(int x, const vector<string>& vstr = { "string", "iterator" })
			:_a(x)
			, _vstr(vstr)
		{}

		int _a;
		vector<string> _vstr;

		static Singleton* _sint;
	};

	Singleton* Singleton::_sint = nullptr;

	struct GC
	{
		GC()
		{}

		~GC()
		{
			Singleton::DestroyInstance();
		}
	};
	GC gc;
}

int main()
{
	lazy::Singleton* sint = lazy::Singleton::GetInstance();
	// lazy::Singleton::DestroyInstance();



	// hunger::Singleton* sint = hunger::Singleton::GetInstance();

	// StackOnly so = StackOnly::GetInstance();
	
	return 0;
}





















